/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.bemanager.dependency;

import com.inspur.edp.bef.bemanager.util.BefFileUtil;
import com.inspur.edp.lcm.metadata.api.service.FileService;
import com.inspur.edp.lcm.metadata.common.FileServiceImp;
import com.inspur.edp.lcm.metadata.common.logging.MvnStreamConsumer;
import com.inspur.edp.lcm.metadata.core.exception.MvnExceptionHandler;
import java.io.File;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.apache.maven.shared.invoker.DefaultInvocationRequest;
import org.apache.maven.shared.invoker.DefaultInvoker;
import org.apache.maven.shared.invoker.InvocationRequest;
import org.apache.maven.shared.invoker.InvocationResult;
import org.apache.maven.shared.utils.cli.CommandLineException;
import org.codehaus.plexus.util.StringUtils;

@Slf4j
public class ManageProjectDependencyUtil {

  private FileService fileService;
  private String mavenHomePath;

  private final DefaultInvoker invoker;

  private final InvocationRequest request;

  private final MvnStreamConsumer mvnStreamConsumer;

  private String errorMessage;

  private ManageProjectDependencyUtil() {
    invoker = new DefaultInvoker();
    request = new DefaultInvocationRequest();
    mvnStreamConsumer = new MvnStreamConsumer();
  }

  public static ManageProjectDependencyUtil getInstance() {
    return new ManageProjectDependencyUtil();
  }


  ModifyPomUtil modifyPomUtil = ModifyPomUtil.getInstance();

  public void addDefaultProjectDependency(String javaProjPath) {
//		String currentJarPath = getServerPath() + "\\platform\\common\\libs";
    String absoluteProjPath = getAbsolutePath(javaProjPath);
    // 添加基本依赖 cef-api等
    addProjectDependency(absoluteProjPath, null, modifyPomUtil.getDefaultDependency());
    // 扩展依赖-jackson等
    modifyPomUtil.modifyPom(absoluteProjPath, modifyPomUtil.getExtendDependency());
    // 添加sgf依赖
    modifyPomUtil.modifyPom(absoluteProjPath, modifyPomUtil.getSgfExtendDependency());
  }

  public void addProjectDependency(String projectPath, String currentJarPath,
      ArrayList<MavenDependency> dependencyArrayList) {
    // 安装jar包到maven仓库
    installPackage(projectPath, currentJarPath, dependencyArrayList);
    // 修改pom文件
    modifyPomUtil.modifyPom(projectPath, dependencyArrayList);
  }

  /**
   * 安装{projectPath}jar包到maven仓库
   *
   * @param projectPath
   * @param currentJarPath
   * @param dependencyArrayList
   */
  public void installPackage(String projectPath, String currentJarPath,
      ArrayList<MavenDependency> dependencyArrayList) {
    // 组装命令
//		String command = String.format("cmd /c cd %s", projectPath);
//		Process process = null;
    String command = null;
    if (currentJarPath != null && !currentJarPath.isEmpty()) {
      String addDependencyCommand = "mvn install:install-file -DgroupId=%1$s " +
          "-DartifactId=%2$s -Dversion=%3$s -Dpackaging=jar -Dfile=%4$s";
      for (MavenDependency dependency : dependencyArrayList) {
        String addCommand = String.format(addDependencyCommand, dependency.getGroupId(),
            dependency.getArtifactId(), dependency.getVersion(),
            getPathString(String.format(currentJarPath + "\\%1$s",
                dependency.getFile())));
        command = command.concat(" && " + addCommand);
      }
      exeMavenCommand(projectPath, null, command);
    }
//		BefFileUtil.excecuteCommand(process, command, "添加bef相关jar包");
  }

  // region 私有方法

  private String getServerPath() {
    return BefFileUtil.getServerPath();
  }

  private String getPathString(String path) {
    return BefFileUtil.getAbsolutePathString(path);
  }

  private void log(String message) {
    BefFileUtil.log(message);
  }

  private FileService getFileService() {
    if (fileService == null) {
      fileService = BefFileUtil.getService(FileService.class);
    }
    return fileService;
  }

  private String getAbsolutePath(String relativePath) {
    String devPath = getFileService().getDevRootPath();
    return Paths.get(devPath).resolve(relativePath).toString();
  }

  public boolean exeMavenCommand(String javaCodePath, String mavenPath, String goal) {
    initInvoker();

    invoker.setWorkingDirectory(new File(javaCodePath));

    List<String> goals = handleGoul(goal, mavenPath);
    request.setGoals(goals);

    try {
      mvnStreamConsumer.setExceptionString("");
      InvocationResult result = invoker.execute(request);
      int resultNum = result.getExitCode();
      if (resultNum == 0) {
        return true;
      }

      if (resultNum == 1) {
        final String exceptionString = mvnStreamConsumer.getExceptionString();
        if (!exceptionString.isEmpty()) {
          MvnExceptionHandler mvnExceptionHandler = new MvnExceptionHandler();
          errorMessage = "";
          errorMessage = mvnExceptionHandler.handleMessage(exceptionString);
          errorMessage = errorMessage.isEmpty() ? "maven编译失败，具体错误请参考日志服务[ERROR]部分" : errorMessage;
        }

        CommandLineException executionException = result.getExecutionException();
        if (executionException != null) {
          throw executionException;
        }
        return false;
      }
    } catch (Exception e) {
      log.error("执行maven命令失败", e);
      e.printStackTrace();
    }
    return false;
  }

  private void initInvoker() {
    initMavenHomePath();
    invoker.setMavenHome(new File(mavenHomePath));
    request.setOutputHandler(mvnStreamConsumer).setBatchMode(true);
  }

  private void initMavenHomePath() {
    if (!StringUtils.isEmpty(mavenHomePath)) {
      return;
    }

    if (System.getenv("MAVEN_HOME") != null) {
      mavenHomePath = System.getenv("MAVEN_HOME");
    } else if (System.getenv("M2_HOME") != null) {
      mavenHomePath = System.getenv("M2_HOME");

      invoker.setMavenHome(new File(System.getenv("M2_HOME")));
    } else {
      String systemPath = System.getenv("Path");
      if (systemPath != null) {
        String[] paths = systemPath.split("\\;");
        for (String path : paths) {
          if (path.contains("maven")) {
            mavenHomePath = path.substring(0, path.length() - 4);
          }
        }
      }
    }
    if (StringUtils.isEmpty(mavenHomePath)) {
      throw new IllegalArgumentException("请配置maven环境变量！MAVEN_HOME=....");
    }


  }

  private List<String> handleGoul(String goal, String mavenPath) {
    List<String> goals = new ArrayList<>();

    StringBuilder goalSb = new StringBuilder(goal);
    String settingsPath = mavenPath + File.separator + "config" + File.separator + "settings.xml";
    FileServiceImp fileService = new FileServiceImp();
    if (fileService.isFileExist(settingsPath)) {
      goalSb.append(" -s ").append(settingsPath);
    } else {
      log.warn("配置文件" + settingsPath + "不存在，使用默认settings.xml配置");
    }

    goals.add(goalSb.toString());
    return goals;
  }
  // endregion
}
